
import { friendData, FRIEND_TYPE } from "./util/friendData";
import { GCtrl } from "./util/GCtrl";


export class TongXunLuData {
    private constructor() {
        this.onEvent();
        // this.getAllFriendData();
    };
    private static m_pInstance: TongXunLuData = null;
    public static getInstance() {
        if (!this.m_pInstance) {
            this.m_pInstance = new TongXunLuData();
        }
        return this.m_pInstance;
    }
    private accountInfo: any = {};
    /**
     * 所有好友分组后的数据格式{A: {'1234567': data, '7984651': data}, B: {...}, ...}
     */
    private groupUserDataArr: any = null;
    private userDataArr: any = {};//未分组数据
    private userIdArr: number[] = [];// 存储好友ID
    private friendNumEveryGroup: any = {};

    private onEvent() {
        GCtrl.eventIndex['ServerNtc_TongXunLuData'] = cc.vv.eventCustom.on("ServerNtc", this.serverNtc.bind(this));
        GCtrl.eventIndex['logout_txld'] = cc.vv.eventCustom.on('logout', this.logout.bind(this), this);
    }
    private offEvent() {
        GCtrl.eventIndex['logout_txld'] && (cc.vv.eventCustom.off('logout', GCtrl.eventIndex['logout_txld']), delete GCtrl.eventIndex['logout_txld']);
        GCtrl.eventIndex['ServerNtc_ TongXunLuData'] && cc.vv.eventCustom.off("ServerNtc", GCtrl.eventIndex['ServerNtc_ TongXunLuData']);
        delete GCtrl.eventIndex['ServerNtc_TongXunLuData'];
    }

    //---------------------------------------
    //数据获取
    //---------------------------------------


    private getAllFriendData() {
        let friendsArr = null;
        let friendsData: friendData[] = [];
        let b = false;
        this.userIdArr = [];
        if (GCtrl.dataConfig.SelfData == null || GCtrl.dataConfig.SelfData == void 0) {
            let key = GCtrl.dataConfig.TONG_XUN_LU_KEY;
            this.userIdArr = JSON.parse(cc.sys.localStorage.getItem(this.accountInfo.phone_num + '_' + key)) || [];
            for (let i in this.userIdArr) {
                let userId = this.userIdArr[i];
                let userData = this.getLocalStorage(userId);
                userData && friendsData.push(userData);
            }
        }
        else {
            this.groupUserDataArr = {};
            this.userDataArr = {};
            b = true;
            friendsArr = GCtrl.dataConfig.SelfData.friend_list;
            if (!friendsArr) return false;
            for (let i in friendsArr) {
                let _userData = friendsArr[i];
                let _friendData = friendData.s2cData(_userData);
                _friendData.friendType = FRIEND_TYPE.Friend;
                friendsData.push(_friendData);
            }
        }
        return this.initFriend(friendsData, b);
    }
    private searchUser(Id: number, dataList: any = null): friendData {
        if (Id == null || Id == void 0) return null;
        let userDataList = this.groupUserDataArr;
        dataList && (userDataList = dataList);
        for (let i in userDataList) {
            let friendDataArr = userDataList[i];
            if (friendDataArr[Id]) return friendDataArr[Id];
        }
        return null;
    }
    private requestData(msgType: string, msg: any, callback = null, ...args) {
        cc.vv.GLUtils.sendRequest(msgType, msg, function (error, data) {
            if (data.errorcode) {
                cc.vv.GLUtils.showTips(data.errordes);
            } else {
                callback && callback(data, ...args);
            }
        }.bind(this));
    }

    private getLocalStorage(Id: number) {
        let key = GCtrl.dataConfig.TONG_XUN_LU_KEY;
        let userDataJson = cc.sys.localStorage.getItem(this.accountInfo.phone_num + '_' + key + '_' + Id);
        if (!userDataJson) return;
        let userData: friendData = JSON.parse(userDataJson);
        return userData;
    }


    //---------------------------------------
    //数据操作
    //---------------------------------------


    private initFriend(_data: friendData[], b: boolean) {
        if (!_data) return false;
        this.groupUserDataArr = {};   
        this.friendNumEveryGroup = {};   
        for (let i in _data) {
            let name = _data[i].remarkName || _data[i].name;
            let SZM = GCtrl.zw2py.makeSZM(name);
            this.groupUserDataArr[SZM] || (this.groupUserDataArr[SZM] = {});
            this.friendNumEveryGroup[SZM] || (this.friendNumEveryGroup[SZM] = []);
            this.groupUserDataArr[SZM][_data[i].Id] ||
                (
                    this.groupUserDataArr[SZM][_data[i].Id] = _data[i],
                    this.friendNumEveryGroup[SZM].indexOf(_data[i].Id) == -1 && this.friendNumEveryGroup[SZM].push(_data[i].Id),
                    this.userIdArr.indexOf(_data[i].Id) == -1 && this.userIdArr.push(_data[i].Id)
                );
        }
        this.sortGroup();
        let _st = new Date().getTime();
        cc.log("startTime: ", _st);
        b && this.contrastData();
        cc.log("endTime: ", new Date().getTime());
        cc.log("offTime: ", new Date().getTime() - _st);
        return true;
    }

    private serverNtc(data: any) {
        if (!data) return;
        if (data.errorcode) return;
        else {
            let ntc = data[0];
            let new_fri_arr = ntc.new_fri;
            let del_fri_arr = ntc.del_fri;
            if (new_fri_arr && new_fri_arr.length) {
                for (let i in new_fri_arr) {
                    let userData = friendData.s2cData(new_fri_arr[i]);
                    if (!this.searchUser(userData.Id)) {
                        this.addFriend(userData);
                        return;
                    }
                }
            }
            if (del_fri_arr && del_fri_arr.length) {
                for (let i in del_fri_arr) {
                    let friend_id = del_fri_arr[i];
                    this.deleteFriendLocal(friend_id);
                }
            }
        }
    }

    private addFriend(userData: friendData) {
        if (!userData) return false;
        userData.friendType = FRIEND_TYPE.Friend;
        let SZM = GCtrl.zw2py.makeSZM(userData.name);
        if (!this.groupUserDataArr) this.groupUserDataArr = {};
        if (this.groupUserDataArr[SZM]) {
            if (!this.groupUserDataArr[SZM][userData.Id]) {
                this.groupUserDataArr[SZM][userData.Id] = userData;
                this.userDataArr[userData.Id] = userData;
            }
            else {
                return false;
            }
        }
        else {
            this.groupUserDataArr[SZM] = {};
            this.groupUserDataArr[SZM][userData.Id] = userData;
            this.userDataArr[userData.Id] = userData;
        }
        this.sortGroup();
        cc.vv.eventCustom.emit('addFriendSuccess', userData.Id, SZM);
        this.setLocalStorage(userData.Id, userData);
        this.userIdArr.push(userData.Id);
        return true;
    }
    private deleteFriendLocal(Id: number) {
        if (Id == null || Id == void 0) return false;
        for (let i in this.groupUserDataArr) {
            let friendDataArr = this.groupUserDataArr[i];
            let b_empty = true;
            if (friendDataArr[Id]) {
                delete friendDataArr[Id];
                delete this.userDataArr[Id];
                for (let j in friendDataArr) {
                    b_empty = false;
                    break;
                }
                if (b_empty) {
                    delete this.groupUserDataArr[i];
                }
                cc.vv.chatMgr.setNewMsgNum(Id, 0);
                cc.vv.eventCustom.emit('deleteFriendSuccess', Id);
                this.removeLocalStorage(Id);
                let index = this.userIdArr.indexOf(Id);
                index != -1 && this.userIdArr.splice(index, 1);
                return true;
            }
        }
        return false;
    }
    private changeGroup(userData: friendData, oldName: string) {
        if (!userData) return null;
        let Id = userData.Id;
        let name = userData.remarkName || userData.name;
        let nSZM = GCtrl.zw2py.makeSZM(name);
        let oSZM = GCtrl.zw2py.makeSZM(oldName);
        if (nSZM == oSZM) return false;
        let nG = this.groupUserDataArr[nSZM];
        let oG = this.groupUserDataArr[oSZM];
        if (!nG) nG = this.groupUserDataArr[nSZM] = {};
        //加入新分组
        if (!nG[Id]) nG[Id] = userData;
        //从旧组拿掉
        if (oG[Id]) {
            delete oG[Id];
            //该组现在是否还有其他成员
            let b = true;
            for (let i in oG) { b = false; break; }
            if (b) delete this.groupUserDataArr[oSZM];
        }
        this.sortGroup();
        return { newGroup: nSZM, oldGroup: oSZM };
    }
    private sortGroup() {
        let dataArr: any[] = [];
        for (let i in this.groupUserDataArr) {
            dataArr.push({ i, data: this.groupUserDataArr[i] });
        }
        dataArr = dataArr.sort((a, b) => {
            if (a.i > b.i) return 1;
            else if (a.i < b.i) return -1;
            return 0;
        });
        this.groupUserDataArr = {};
        for (let i in dataArr) {
            this.groupUserDataArr[dataArr[i].i] = dataArr[i].data;
        }
    }
    private setLocalStorage(Id: number, userData: friendData = null) {
        userData || (userData = this.searchUser(Id));
        if (!userData) return false;
        let key = GCtrl.dataConfig.TONG_XUN_LU_KEY;
        cc.sys.localStorage.setItem(this.accountInfo.phone_num + '_' + key + '_' + Id, JSON.stringify(userData));
        return true;
    }
    private removeLocalStorage(Id: number) {
        let key = GCtrl.dataConfig.TONG_XUN_LU_KEY;
        let localData = cc.sys.localStorage.getItem(this.accountInfo.phone_num + '_' + key + '_' + Id);
        if (!localData) return false;
        localData && (cc.sys.localStorage.removeItem(this.accountInfo.phone_num + '_' + key + '_' + Id));
        return true;
    }    
    private saveStorage() {
        let key = GCtrl.dataConfig.TONG_XUN_LU_KEY;
        let f = (group, name) => {
            let fneg = this.friendNumEveryGroup[name];
            let length = fneg.length;
            let step = 10;
            let count = Math.ceil(length / step);
            let reapt = 0;
            let j = 0;
            GCtrl.self.schedule(() => {
                ++reapt;
                for (; j < length && j < reapt * step; ++j) {
                    let userData = group[fneg[j]];
                    let jsonStr = JSON.stringify(userData);
                    jsonStr && cc.sys.localStorage.setItem(this.accountInfo.phone_num + '_' + key + '_' + userData.Id, jsonStr);
                }
            }, 0, count);
        }
        for (let i in this.groupUserDataArr) {
            let userDataArr = this.groupUserDataArr[i];
            f(userDataArr, i);
            // for (let j in userDataArr) {
            //     let userData = userDataArr[j];
            //     let jsonStr = JSON.stringify(userData);
            //     jsonStr && cc.sys.localStorage.setItem(this.accountInfo.phone_num + '_' + key + '_' + userData.Id, jsonStr);
            // }
        }
        cc.sys.localStorage.setItem(this.accountInfo.phone_num + '_' + key, JSON.stringify(this.userIdArr));
        return true;
    }
    //对比本地缓存和服务器数据的差异(以服务器为准)
    private contrastData() {
        let key = GCtrl.dataConfig.TONG_XUN_LU_KEY;       
         let f = (group, name) => {
            let fneg = this.friendNumEveryGroup[name];
            let length = fneg.length;
            let step = 10;
            let count = Math.ceil(length / step);
            let reapt = 0;
            let j = 0;
            GCtrl.self.schedule(() => {
                ++reapt;
                for (; j < length && j < reapt * step; ++j) {
                    let userData_server = group[fneg[j]];
                    let Id = userData_server.Id;
                    let userData_local = JSON.parse(cc.sys.localStorage.getItem(this.accountInfo.phone_num + '_' + key + '_' + Id));
                    userData_local || (userData_local = {});
                    for (let k in userData_server) {
                        userData_local[k] = friendData.contrastData(k, userData_local[k], userData_server[k]);
                    }
                    this.groupUserDataArr[name][Id] = userData_local;
                    this.userDataArr[Id] = this.groupUserDataArr[name][Id];
                }
            }, 0, count);
        }
        for (let i in this.groupUserDataArr) {
            let userDataArr = this.groupUserDataArr[i];
            f(userDataArr, i);
        };
        return this.saveStorage();
    }
    private logout() {
        this.groupUserDataArr = {};
        this.userDataArr = {};
        this.userIdArr = [];
        this.friendNumEveryGroup = {};
        TongXunLuData.m_pInstance = null;
        this.offEvent();
    }

    //--------------
    init() {
        this.accountInfo = cc.vv.GLUtils.getAccountInfo();
        this.getAllFriendData();
    }

    //---------------------------------------
    //数据获取
    //---------------------------------------

    /**
     * 获取分组后的全部好友数据
     * @param eventName 接收好友数据事件名
     */
    public getData(eventName: string = '') {
        cc.vv.eventCustom.emit(eventName, this.groupUserDataArr);
        return this.groupUserDataArr;
    }
    /**
     * 获取未分组的全部好友数据
     * @param eventName 接收好友数据事件名
     */
    public getUngroupData(eventName: string = '') {
        cc.vv.eventCustom.emit(eventName, this.userDataArr);
        return this.userDataArr;
    }
    /**
     * 获取指定ID好友数据
     * @param userId 好友ID
     * @param eventName 接收好友数据事件名
     */
    public getUserData(userId: number, eventName: string = '') {
        if (userId == null || userId == void 0) return null;
        let _user: friendData = this.searchUser(userId);
        cc.vv.eventCustom.emit(eventName, _user);
        return _user;
    }
    /**
     * 筛选符合条件的好友
     * @param condition 筛选条件(name, ID)
     */
    public shaiXuanData(condition: string = '') {
        if (condition == '') return this.groupUserDataArr;
        let _hArr: any = {};
        let _fArr: any = {};
        let { ...tempArr } = this.groupUserDataArr;
        for (let i in tempArr) {
            let friendDataArr = tempArr[i];
            let b_add = false;
            _hArr[i] = {};
            for (let j in friendDataArr) {
                let friendData = friendDataArr[j];
                let name = friendData.name;
                let num = friendData.phoneNum;
                let id = friendData.Id + "";
                let remarkName = friendData.remarkName + "";
                if (name.indexOf(condition) == -1 && num.indexOf(condition) == -1
                    && id.indexOf(condition) == -1 && remarkName.indexOf(condition) == -1) {
                }
                else {
                    b_add = true;
                    _hArr[i][j] = friendData;
                    _fArr[j] = friendData;
                }
            }
            if (!b_add) delete _hArr[i];
        }
        return { withGroup: _hArr, withoutGroup: _fArr };
    }
    /**
     * 获取指定用户未读消息数
     * @param Id 用户ID
     */
    public getUnreadMsgNum(Id: number) {
        let userData = this.searchUser(Id);
        if (!userData) return 0;
        return userData.unreadMsgNum;
    }
    /**
     * 获取指定群数据
     * @param Id 群ID
     */
    public getlocaluserData(Id: number) {
        let userData = this.getLocalStorage(Id)
        if (!userData) return null;
        return userData;
    }

    /**
     * 获取指定用户最新已读消息ID
     * @param Id 用户ID
     */
    public getReadedMsgId(Id: number) {
        // let userData = this.searchUser(Id);
        // if (!userData) return 0;
        // return userData.readedMsgId;
        let userData = this.getLocalStorage(Id)
        if (!userData) return 0;
        return userData.readedMsgId;
    }

    //---------------------------------------
    //数据操作
    //---------------------------------------

    /**
     * 将用户数据分组
     * @param _data 
     */
    public washDataArr(_data: friendData[]) {
        if (!_data) return null;
        let groupUserDataArr: any = {};
        for (let i in _data) {
            let SZM = GCtrl.zw2py.makeSZM(_data[i].name);
            if (!groupUserDataArr[SZM])
                groupUserDataArr[SZM] = {};
            if (!groupUserDataArr[SZM][_data[i].Id]) {
                groupUserDataArr[SZM][_data[i].Id] = _data[i];
            }
        }
        return groupUserDataArr;
    }
    /**
     * 删除好友
     * @param Id 好友ID
     */
    public deleteFriend(Id: number) {
        if (Id == null || Id == void 0) return false;
        this.requestData('DeleteFriend', { user_id: Id });
        return false;
    }
    /**
     * 设置好友备注
     * @param newRemarkName 新备注名
     * @param Id 好友ID
     */
    public changeRemarkName(newRemarkName: string, Id: number) {
        if (Id == null || Id == void 0) return false;
        for (let i in this.groupUserDataArr) {
            let friendDataArr = this.groupUserDataArr[i];
            if (friendDataArr[Id]) {
                let _friendData = friendDataArr[Id];
                let oldName = _friendData.remarkName || _friendData.name;
                _friendData.remarkName = newRemarkName;
                this.requestData('SetComments', { comments: newRemarkName, user_id: Id });
                //备注换了后, 该好友所在分组也需更换
                let groupInfo = this.changeGroup(_friendData, oldName);
                cc.vv.eventCustom.emit('changeRemarkNameSuccess', newRemarkName, Id, groupInfo);
                this.setLocalStorage(Id, _friendData);
                return true;
            }
        }
    }
    /**
     * 设置好友聊天免打扰模式
     * @param Id 好友ID
     * @param b true开启 false关闭
     */
    public setBotherState(Id: number, b: boolean) {
        let userData = this.getUserData(Id);
        if (!userData) return false;
        if (userData.isDontBother != b && typeof b == 'boolean') {
            userData.isDontBother = b;
            this.setLocalStorage(Id, userData);
            return true;
        }
        return false;
    }
    /**
     * 设置好友聊天置顶模式
     * @param Id 好友ID
     * @param b true开启 false关闭
     */
    public setTopState(Id: number, b: boolean) {
        let userData = this.getUserData(Id);
        if (!userData) return false;
        if (userData.isTop != b && typeof b == 'boolean') {
            userData.isTop = b;
            this.setLocalStorage(Id, userData);
            return true;
        }
        return false;
    }
    /**
     * 设置显示昵称
     * @param groupId 群ID
     * @param b true开启 false关闭
     */
    public setShowName(Id: number, b: boolean) {
        let userData = this.getUserData(Id);
        if (!userData) return false;
        if (userData.isShowName != b && typeof b == 'boolean') {
            userData.isShowName = b;
            cc.vv.eventCustom.emit('setShowNameSuccess', Id, b);
            this.setLocalStorage(Id, userData);
            return true;
        }
    }
    /**
     * 清除和所有好友的聊天记录
     */
    public ClearAllSession() {
        for (let i in this.groupUserDataArr) {
            let userDataArr = this.groupUserDataArr[i];
            for (let j in userDataArr) {
                let userData = userDataArr[j];
                cc.vv.chatMgr.clearOneSessionMessage(userData.Id, false);
            }
        }
    }
    /**
     * 设置指定用户未读消息数
     * @param Id 用户ID
     * @param num 消息数
     */
    public setUnreadMsgNum(Id: number, num: number) {
        let userData = this.searchUser(Id);
        if (!userData || num == null || num == void 0) return false;
        userData.unreadMsgNum = num;
        this.setLocalStorage(Id, userData);
        return true;
    }

    /**
     * 设置指定用户最新已读消息ID
     * @param Id 用户ID
     * @param index 消息ID
     */
    public setReadedMsgId(Id: number, index: number) {
        let userData = this.searchUser(Id);
        if (!userData || index == null || index == void 0) return false;
        userData.readedMsgId = index;
        cc.vv.chatMgr.setNewMsgNum(Id, 0);
        cc.vv.eventCustom.emit('updateNewMsgNum', Id, 0);
        this.setLocalStorage(Id, userData);
        return true;
    }
    /**
     * 是否是自己好友
     * @param Id 用户ID
     */
    public isFriend(Id: number) {
        return !!this.searchUser(Id);
    }
    /**
     * 获取好友数量
     */
    public getFriendCount() {
        return this.userIdArr.length;
    }
}